using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;

namespace MCromwell.StaffIntranet.Core
{
    public class ValidStaffPhotoSpecification : ISpecification<Staff>
    {
        private const int MIN_HEIGHT = 200;
        private const int MIN_WIDTH = 166;
        private const int MAX_HEIGHT = 300;
        private const int MAX_WIDTH = 266;
        
        private bool IsImageSmallEnough(byte[] imageData, DomainObjectValidationResult result)
        {
            using (Image image = ConvertFrom(imageData))
            {
                if ((image.Height > MAX_HEIGHT) || (image.Width > MAX_WIDTH))
                {
                    result.Register(new ValidationResultItem("imagetoobig", string.Format("image supplied is too big, maximum dimensions are, height: {0}, width: {1}", MAX_HEIGHT, MAX_WIDTH)));
                    return false;
                }
            }

            return true;
        }

        private static Image ConvertFrom(byte[] imageData)
        {
            Image image = null;
            using (MemoryStream ms = new MemoryStream(imageData))
            {
                image = Image.FromStream(ms, false, true);
            }

            return image;
        }

        private static bool IsImageBigEnough(byte[] imageData, DomainObjectValidationResult result)
        {
            using (Image image = ConvertFrom(imageData))
            {
                if ((image.Height < MIN_HEIGHT) || (image.Width < MIN_WIDTH))
                {
                    result.Register(new ValidationResultItem("imagetoosmall", string.Format("image supplied is too small, minimum dimensions are, height: {0}, width: {1}", MIN_HEIGHT, MIN_WIDTH)));
                    return false;
                }
            }

            return true;
        }

        private static bool IsValidImage(DomainObjectValidationResult result, byte[] imageData)
        {
            if ((imageData == null) || (imageData.Length <= 0))
            {
                RegisterInvalidImage(result);
                return false;
            }

            try
            {
                ConvertFrom(imageData);
            }
            catch (Exception)
            {
                RegisterInvalidImage(result);
                return false;
            }

            return true;
        }

        private static void RegisterInvalidImage(DomainObjectValidationResult result)
        {
            result.Register(new ValidationResultItem("invalidimage","image is invalid"));
        }
                
        public DomainObjectValidationResult ResultsOf(Staff item)
        {
            var imageData = item.Photo;
            DomainObjectValidationResult result = new DomainObjectValidationResult();
            bool valid = true;

            valid &= IsValidImage(result, imageData);

            if (valid)
                valid &= IsImageBigEnough(imageData, result);

            if (valid)
                IsImageSmallEnough(imageData, result);

            return result;
        }

    }
}
